using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using KnowledgeQA.Data;
using KnowledgeQA.Models.Entities;
using KnowledgeQA.Models.DTOs;
using KnowledgeQA.Services.Interfaces;
using KnowledgeQA.Core.Interfaces;

namespace KnowledgeQA.Services.Implementations
{
    /// <summary>
    /// 问答服务实现类
    /// </summary>
    public class QAService : IQAService
    {
        private readonly KnowledgeQADbContext _context;
        private readonly ILogger<QAService> _logger;
        private readonly IAIService _aiService;
        private readonly IVectorService _vectorService;

        public QAService(KnowledgeQADbContext context, ILogger<QAService> logger, IAIService aiService, IVectorService vectorService)
        {
            _context = context;
            _logger = logger;
            _aiService = aiService;
            _vectorService = vectorService;
        }

        public async Task<AskQuestionResponse> AskQuestionAsync(AskQuestionRequest request)
        {
            try
            {
                var stopwatch = System.Diagnostics.Stopwatch.StartNew();
                _logger.LogInformation("开始处理问答请求，问题: {Question}", request.Question);

                // 1. 生成问题的向量嵌入
                var questionEmbedding = await _aiService.GenerateEmbeddingAsync(request.Question);
                _logger.LogInformation("问题向量嵌入生成完成，维度: {Dimension}", questionEmbedding.Length);

                // 2. 构建检索参数
                var retrievalParams = request.RetrievalParameters ?? new RetrievalParameters();
                var topK = retrievalParams.TopK;
                var minRelevanceScore = retrievalParams.MinRelevanceScore;

                // 3. 构建过滤条件
                var filter = new Dictionary<string, object>();
                if (retrievalParams.CategoryIds?.Any() == true)
                {
                    filter["categoryId"] = retrievalParams.CategoryIds;
                }
                if (retrievalParams.Tags?.Any() == true)
                {
                    filter["tags"] = retrievalParams.Tags;
                }

                // 4. 执行向量相似度搜索
                var searchResults = await _vectorService.SearchAsync(
                    questionEmbedding, 
                    topK, 
                    minRelevanceScore, 
                    filter
                );

                _logger.LogInformation("向量搜索完成，找到 {Count} 个相关文档块", searchResults.Count);

                // 5. 获取检索到的文档块详细信息
                var retrievedChunks = new List<RetrievedChunkInfo>();
                var contextBuilder = new System.Text.StringBuilder();

                if (searchResults.Any())
                {
                    // 获取文档块详细信息
                    var chunkIds = searchResults.Select(r => r.VectorId).ToList();
                    var chunks = await GetDocumentChunksAsync(chunkIds);

                    foreach (var searchResult in searchResults)
                    {
                        var chunk = chunks.FirstOrDefault(c => c.Id.ToString() == searchResult.VectorId);
                        if (chunk != null)
                        {
                            var chunkInfo = new RetrievedChunkInfo
                            {
                                ChunkId = chunk.Id,
                                DocumentId = chunk.DocumentId,
                                DocumentTitle = chunk.Document?.Title ?? "未知文档",
                                Content = chunk.Content,
                                RelevanceScore = searchResult.Score,
                                ChunkIndex = chunk.ChunkIndex
                            };

                            retrievedChunks.Add(chunkInfo);

                            // 构建上下文
                            contextBuilder.AppendLine($"文档: {chunkInfo.DocumentTitle}");
                            contextBuilder.AppendLine($"内容: {chunk.Content}");
                            contextBuilder.AppendLine();
                        }
                    }
                }

                // 6. 构建完整的上下文
                var context = contextBuilder.ToString().Trim();
                var fullContext = string.IsNullOrEmpty(request.Context) 
                    ? context 
                    : $"{request.Context}\n\n{context}";

                // 7. 构建RAG提示词
                var ragPrompt = BuildRAGPrompt(request.Question, fullContext, retrievedChunks);

                // 8. 调用AI服务生成回答
                var aiResponse = await _aiService.GenerateAnswerAsync(
                    ragPrompt, 
                    fullContext, 
                    request.ModelParameters
                );

                // 9. 构建响应
                var response = new AskQuestionResponse
                {
                    Answer = aiResponse.Success ? aiResponse.Content : "抱歉，我无法生成回答。",
                    RetrievedChunks = retrievedChunks,
                    ModelName = request.ModelName ?? _aiService.ModelName,
                    ProcessingTime = stopwatch.ElapsedMilliseconds,
                    ConfidenceScore = aiResponse.Success ? aiResponse.ConfidenceScore : 0.0,
                    UsedRAG = retrievedChunks.Any()
                };

                stopwatch.Stop();
                response.ProcessingTime = stopwatch.ElapsedMilliseconds;

                _logger.LogInformation("问答完成，问题: {Question}, 处理时间: {ProcessingTime}ms, 使用RAG: {UsedRAG}, 置信度: {ConfidenceScore}", 
                    request.Question, response.ProcessingTime, response.UsedRAG, response.ConfidenceScore);

                return response;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "问答失败，问题: {Question}", request.Question);
                throw;
            }
        }

        public async Task<ChatSessionDTO> CreateSessionAsync(CreateSessionRequest request)
        {
            try
            {
                var session = new ChatSession
                {
                    Title = request.Title,
                    Description = request.Description,
                    UserId = request.UserId,
                    ModelName = request.ModelName ?? _aiService.ModelName,
                    Configuration = request.Configuration != null ? System.Text.Json.JsonSerializer.Serialize(request.Configuration) : null,
                    Status = "Active"
                };

                _context.ChatSessions.Add(session);
                await _context.SaveChangesAsync();

                _logger.LogInformation("聊天会话创建成功，ID: {SessionId}", session.Id);
                return MapToSessionDTO(session);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建聊天会话失败");
                throw;
            }
        }

        public async Task<PagedResponse<ChatSessionDTO>> GetSessionsAsync(string? userId = null, int pageIndex = 1, int pageSize = 20)
        {
            try
            {
                var query = _context.ChatSessions
                    .Where(s => !s.IsDeleted);

                if (!string.IsNullOrEmpty(userId))
                {
                    query = query.Where(s => s.UserId == userId);
                }

                var totalCount = await query.CountAsync();

                var sessions = await query
                    .OrderByDescending(s => s.LastActiveAt)
                    .Skip((pageIndex - 1) * pageSize)
                    .Take(pageSize)
                    .ToListAsync();

                var sessionDtos = sessions.Select(MapToSessionDTO).ToList();

                return PagedResponse<ChatSessionDTO>.Create(sessionDtos, totalCount, pageIndex, pageSize);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取聊天会话列表失败");
                throw;
            }
        }

        public async Task<ChatSessionDTO?> GetSessionByIdAsync(int sessionId)
        {
            try
            {
                var session = await _context.ChatSessions
                    .Include(s => s.Messages)
                    .FirstOrDefaultAsync(s => s.Id == sessionId && !s.IsDeleted);

                return session != null ? MapToSessionDTO(session) : null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取聊天会话失败，ID: {SessionId}", sessionId);
                throw;
            }
        }

        public async Task<bool> DeleteSessionAsync(int sessionId)
        {
            try
            {
                var session = await _context.ChatSessions.FindAsync(sessionId);
                if (session == null)
                {
                    return false;
                }

                session.IsDeleted = true;
                session.UpdatedAt = DateTime.Now;

                await _context.SaveChangesAsync();

                _logger.LogInformation("聊天会话删除成功，ID: {SessionId}", sessionId);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除聊天会话失败，ID: {SessionId}", sessionId);
                throw;
            }
        }

        public async Task<ChatMessageDTO> SendMessageAsync(SendMessageRequest request)
        {
            try
            {
                var session = await _context.ChatSessions.FindAsync(request.SessionId);
                if (session == null)
                {
                    throw new ArgumentException($"聊天会话不存在，ID: {request.SessionId}");
                }

                // 创建用户消息
                var userMessage = new ChatMessage
                {
                    SessionId = request.SessionId,
                    Content = request.Message,
                    MessageType = "User",
                    MessageIndex = await GetNextMessageIndex(request.SessionId),
                    ParentMessageId = request.ParentMessageId,
                    Status = "Completed"
                };

                _context.ChatMessages.Add(userMessage);
                await _context.SaveChangesAsync();

                // 使用RAG生成AI回复
                var ragRequest = new AskQuestionRequest
                {
                    Question = request.Message,
                    ModelName = request.ModelName,
                    ModelParameters = request.ModelParameters,
                    RetrievalParameters = new RetrievalParameters
                    {
                        TopK = 5,
                        MinRelevanceScore = 0.7,
                        IncludeMetadata = true
                    }
                };

                var ragResponse = await AskQuestionAsync(ragRequest);
                
                var aiMessage = new ChatMessage
                {
                    SessionId = request.SessionId,
                    Content = ragResponse.Answer,
                    MessageType = "Assistant",
                    MessageIndex = await GetNextMessageIndex(request.SessionId),
                    ParentMessageId = userMessage.Id,
                    Status = ragResponse.UsedRAG ? "Completed" : "Completed",
                    ProcessingTime = ragResponse.ProcessingTime,
                    ModelName = request.ModelName ?? _aiService.ModelName,
                    ModelParameters = request.ModelParameters != null ? System.Text.Json.JsonSerializer.Serialize(request.ModelParameters) : null,
                    ErrorMessage = null
                };

                _context.ChatMessages.Add(aiMessage);

                // 更新会话信息
                session.LastActiveAt = DateTime.Now;
                session.MessageCount = await _context.ChatMessages.CountAsync(m => m.SessionId == request.SessionId);

                await _context.SaveChangesAsync();

                _logger.LogInformation("消息发送成功，会话ID: {SessionId}, 消息ID: {MessageId}, 使用RAG: {UsedRAG}", 
                    request.SessionId, userMessage.Id, ragResponse.UsedRAG);
                return MapToMessageDTO(aiMessage);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送消息失败，会话ID: {SessionId}", request.SessionId);
                throw;
            }
        }

        public async Task<PagedResponse<ChatMessageDTO>> GetSessionMessagesAsync(int sessionId, int pageIndex = 1, int pageSize = 50)
        {
            try
            {
                var query = _context.ChatMessages
                    .Where(m => m.SessionId == sessionId)
                    .OrderBy(m => m.MessageIndex);

                var totalCount = await query.CountAsync();

                var messages = await query
                    .Skip((pageIndex - 1) * pageSize)
                    .Take(pageSize)
                    .ToListAsync();

                var messageDtos = messages.Select(MapToMessageDTO).ToList();

                return PagedResponse<ChatMessageDTO>.Create(messageDtos, totalCount, pageIndex, pageSize);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取会话消息失败，会话ID: {SessionId}", sessionId);
                throw;
            }
        }

        public async Task<bool> SubmitFeedbackAsync(UserFeedbackRequest request)
        {
            try
            {
                var message = await _context.ChatMessages.FindAsync(request.MessageId);
                if (message == null)
                {
                    return false;
                }

                message.UserFeedback = request.Feedback;
                message.FeedbackNote = request.FeedbackNote;
                message.UpdatedAt = DateTime.Now;

                await _context.SaveChangesAsync();

                _logger.LogInformation("用户反馈提交成功，消息ID: {MessageId}, 反馈: {Feedback}", request.MessageId, request.Feedback);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "提交用户反馈失败，消息ID: {MessageId}", request.MessageId);
                return false;
            }
        }

        public async Task<string> ExportSessionAsync(int sessionId, string format = "json")
        {
            try
            {
                var session = await _context.ChatSessions
                    .Include(s => s.Messages.OrderBy(m => m.MessageIndex))
                    .FirstOrDefaultAsync(s => s.Id == sessionId && !s.IsDeleted);

                if (session == null)
                {
                    throw new ArgumentException($"聊天会话不存在，ID: {sessionId}");
                }

                return format.ToLower() switch
                {
                    "json" => System.Text.Json.JsonSerializer.Serialize(session, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }),
                    "txt" => ExportToText(session),
                    "csv" => ExportToCsv(session),
                    _ => throw new ArgumentException($"不支持的导出格式: {format}")
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导出会话失败，会话ID: {SessionId}", sessionId);
                throw;
            }
        }

        public async Task<QAStats> GetQAStatsAsync()
        {
            try
            {
                var stats = new QAStats();

                var sessions = await _context.ChatSessions
                    .Where(s => !s.IsDeleted)
                    .ToListAsync();

                var messages = await _context.ChatMessages
                    .Where(m => m.Status == "Completed")
                    .ToListAsync();

                var today = DateTime.Today;

                stats.TotalSessions = sessions.Count;
                stats.TotalMessages = messages.Count;
                stats.TodaySessions = sessions.Count(s => s.CreatedAt >= today);
                stats.TodayMessages = messages.Count(m => m.CreatedAt >= today);
                stats.AverageResponseTime = messages.Any() ? messages.Average(m => m.ProcessingTime ?? 0) : 0;
                stats.UserSatisfactionScore = 0.85; // 模拟满意度评分

                // 按模型统计使用情况
                stats.UsageByModel = messages
                    .Where(m => !string.IsNullOrEmpty(m.ModelName))
                    .GroupBy(m => m.ModelName!)
                    .ToDictionary(g => g.Key, g => g.Count());

                return stats;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取问答统计信息失败");
                throw;
            }
        }

        private async Task<int> GetNextMessageIndex(int sessionId)
        {
            var maxIndex = await _context.ChatMessages
                .Where(m => m.SessionId == sessionId)
                .MaxAsync(m => (int?)m.MessageIndex) ?? 0;

            return maxIndex + 1;
        }

        private ChatSessionDTO MapToSessionDTO(ChatSession session)
        {
            return new ChatSessionDTO
            {
                Id = session.Id,
                Title = session.Title,
                Description = session.Description,
                UserId = session.UserId,
                Status = session.Status,
                ModelName = session.ModelName,
                LastActiveAt = session.LastActiveAt,
                MessageCount = session.MessageCount,
                CreatedAt = session.CreatedAt,
                UpdatedAt = session.UpdatedAt
            };
        }

        private ChatMessageDTO MapToMessageDTO(ChatMessage message)
        {
            return new ChatMessageDTO
            {
                Id = message.Id,
                SessionId = message.SessionId,
                MessageType = message.MessageType,
                Content = message.Content,
                MessageIndex = message.MessageIndex,
                ParentMessageId = message.ParentMessageId,
                Status = message.Status,
                ProcessingTime = message.ProcessingTime,
                ModelName = message.ModelName,
                RetrievedChunks = new List<RetrievedChunkInfo>(), // 这里应该从数据库获取实际的检索信息
                ErrorMessage = message.ErrorMessage,
                UserFeedback = message.UserFeedback,
                FeedbackNote = message.FeedbackNote,
                CreatedAt = message.CreatedAt
            };
        }

        private string ExportToText(ChatSession session)
        {
            var sb = new System.Text.StringBuilder();
            sb.AppendLine($"会话标题: {session.Title}");
            sb.AppendLine($"创建时间: {session.CreatedAt}");
            sb.AppendLine($"消息数量: {session.MessageCount}");
            sb.AppendLine();

            foreach (var message in session.Messages.OrderBy(m => m.MessageIndex))
            {
                sb.AppendLine($"[{message.CreatedAt:yyyy-MM-dd HH:mm:ss}] {message.MessageType}:");
                sb.AppendLine(message.Content);
                sb.AppendLine();
            }

            return sb.ToString();
        }

        private string ExportToCsv(ChatSession session)
        {
            var sb = new System.Text.StringBuilder();
            sb.AppendLine("时间,类型,内容");

            foreach (var message in session.Messages.OrderBy(m => m.MessageIndex))
            {
                var content = message.Content.Replace("\"", "\"\"");
                sb.AppendLine($"\"{message.CreatedAt:yyyy-MM-dd HH:mm:ss}\",\"{message.MessageType}\",\"{content}\"");
            }

            return sb.ToString();
        }

        /// <summary>
        /// 获取文档块信息
        /// </summary>
        /// <param name="chunkIds">文档块ID列表</param>
        /// <returns>文档块列表</returns>
        private async Task<List<DocumentChunk>> GetDocumentChunksAsync(List<string> chunkIds)
        {
            try
            {
                var ids = chunkIds.Select(id => int.TryParse(id, out var num) ? num : -1)
                                 .Where(id => id > 0)
                                 .ToList();

                if (!ids.Any())
                {
                    return new List<DocumentChunk>();
                }

                var chunks = await _context.DocumentChunks
                    .Include(c => c.Document)
                    .Where(c => ids.Contains(c.Id))
                    .ToListAsync();

                _logger.LogInformation("获取到 {Count} 个文档块", chunks.Count);
                return chunks;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取文档块失败");
                return new List<DocumentChunk>();
            }
        }

        /// <summary>
        /// 构建RAG提示词
        /// </summary>
        /// <param name="question">问题</param>
        /// <param name="context">上下文</param>
        /// <param name="retrievedChunks">检索到的文档块</param>
        /// <returns>RAG提示词</returns>
        private string BuildRAGPrompt(string question, string context, List<RetrievedChunkInfo> retrievedChunks)
        {
            var prompt = new System.Text.StringBuilder();

            // 系统角色定义
            prompt.AppendLine("你是一个专业的知识库问答助手。请基于提供的文档内容回答用户的问题。");
            prompt.AppendLine();

            // 回答要求
            prompt.AppendLine("回答要求：");
            prompt.AppendLine("1. 基于提供的文档内容进行回答");
            prompt.AppendLine("2. 如果文档内容不足以回答问题，请明确说明");
            prompt.AppendLine("3. 回答要准确、简洁、有用");
            prompt.AppendLine("4. 可以引用具体的文档来源");
            prompt.AppendLine();

            // 文档内容
            if (!string.IsNullOrEmpty(context))
            {
                prompt.AppendLine("相关文档内容：");
                prompt.AppendLine(context);
                prompt.AppendLine();
            }

            // 文档来源信息
            if (retrievedChunks.Any())
            {
                prompt.AppendLine("文档来源：");
                foreach (var chunk in retrievedChunks)
                {
                    prompt.AppendLine($"- {chunk.DocumentTitle} (相关度: {chunk.RelevanceScore:F2})");
                }
                prompt.AppendLine();
            }

            // 用户问题
            prompt.AppendLine($"用户问题：{question}");
            prompt.AppendLine();
            prompt.AppendLine("请基于上述文档内容回答用户的问题：");

            return prompt.ToString();
        }

        /// <summary>
        /// 增强的发送消息方法，支持RAG
        /// </summary>
        /// <param name="request">发送请求</param>
        /// <returns>消息信息</returns>
        public async Task<ChatMessageDTO> SendMessageWithRAGAsync(SendMessageRequest request)
        {
            try
            {
                var session = await _context.ChatSessions.FindAsync(request.SessionId);
                if (session == null)
                {
                    throw new ArgumentException($"聊天会话不存在，ID: {request.SessionId}");
                }

                // 创建用户消息
                var userMessage = new ChatMessage
                {
                    SessionId = request.SessionId,
                    Content = request.Message,
                    MessageType = "User",
                    MessageIndex = await GetNextMessageIndex(request.SessionId),
                    ParentMessageId = request.ParentMessageId,
                    Status = "Completed"
                };

                _context.ChatMessages.Add(userMessage);
                await _context.SaveChangesAsync();

                // 使用RAG生成AI回复
                var ragRequest = new AskQuestionRequest
                {
                    Question = request.Message,
                    ModelName = request.ModelName,
                    ModelParameters = request.ModelParameters,
                    RetrievalParameters = new RetrievalParameters
                    {
                        TopK = 5,
                        MinRelevanceScore = 0.7,
                        IncludeMetadata = true
                    }
                };

                var ragResponse = await AskQuestionAsync(ragRequest);

                var aiMessage = new ChatMessage
                {
                    SessionId = request.SessionId,
                    Content = ragResponse.Answer,
                    MessageType = "Assistant",
                    MessageIndex = await GetNextMessageIndex(request.SessionId),
                    ParentMessageId = userMessage.Id,
                    Status = ragResponse.UsedRAG ? "Completed" : "Completed",
                    ProcessingTime = ragResponse.ProcessingTime,
                    ModelName = request.ModelName ?? _aiService.ModelName,
                    ModelParameters = request.ModelParameters != null ? System.Text.Json.JsonSerializer.Serialize(request.ModelParameters) : null,
                    ErrorMessage = null
                };

                _context.ChatMessages.Add(aiMessage);

                // 更新会话信息
                session.LastActiveAt = DateTime.Now;
                session.MessageCount = await _context.ChatMessages.CountAsync(m => m.SessionId == request.SessionId);

                await _context.SaveChangesAsync();

                _logger.LogInformation("RAG消息发送成功，会话ID: {SessionId}, 消息ID: {MessageId}, 使用RAG: {UsedRAG}", 
                    request.SessionId, userMessage.Id, ragResponse.UsedRAG);
                
                return MapToMessageDTO(aiMessage);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "RAG消息发送失败，会话ID: {SessionId}", request.SessionId);
                throw;
            }
        }
    }
} 